iT邦幫忙

2024 iThome 鐵人賽

DAY 26
0
Modern Web

雙向奔赴的websocket與冰冷的react系列 第 26

[day26]WebSocket 與 React 基礎:建立 WebSocket 連接

  • 分享至 

  • xImage
  •  

最後就來慢慢將兩者結合吧,先來基礎連接

建立連接

首先當然是建立兩者的環境

  • CRA
npx create-react-app ws-app
cd ws-app
  • ws
    npm install ws

server.js

環境建好就可以開始寫了,那我們先把ws-server搭起來

const WebSocket = require("ws");

// 創建 WebSocket 服務器,監聽端口 8080
const wss = new WebSocket.Server({ port: 8080 });
// 每當有新的客戶端連接時觸發
wss.on("connection", function connection(ws) {
    console.log("客戶端已連接");
    // 當收到客戶端消息時觸發
    ws.on("message", function incoming(message) {
        ws.send(`ws: ${message}`);
    });
    // 當客戶端斷開連接時觸發
    ws.on("close", function close() {
        console.log("客戶端已斷開連接");
    });
});
// 定時每 10 秒廣播當前連接的客戶端數量
setInterval(() => {
    const numClients = wss.clients.size; // 當前連接的客戶端數量
    // 向每個已連接的客戶端發送當前連接數量
    console.log("當前連接的客戶端數量:", numClients);
}, 10000);

console.log("WebSocket 服務器運行在 ws://localhost:8080");

註解直接放進去,特別的就是監控Client的連接數量,該怎麼說在用React連接時有很多的意外,就裝了這個好觀察

App.js

就直接把原本的App.js替換成以下

import React, { useEffect, useState } from 'react';

function WebSocketComponent() {
  const [message, setMessage] = useState('');
  const [serverMessage, setServerMessage] = useState('');
  const [ws, setWs] = useState(null);
  useEffect(() => {
    // 建立 WebSocket 連接
    const ws = new WebSocket('ws://localhost:8080');
    // 當 WebSocket 連接成功時觸發
    ws.onopen = () => {
      console.log('WebSocket 連接成功');
      setWs(ws);
    };

    // 當從服務器收到消息時觸發
    ws.onmessage = (event) => {
      console.log('收到服務器消息:', event.data);
      setServerMessage(event.data); // 更新收到的消息
    };

    // 當 WebSocket 連接關閉時觸發
    ws.onclose = () => {
      console.log('WebSocket 連接關閉');
    };

    // 當 WebSocket 出現錯誤時觸發
    ws.onerror = (error) => {
      console.error('WebSocket 錯誤:', error);
    };

    // 在組件卸載時關閉 WebSocket 連接
    return () => {
      ws.close();
    };
  }, []);
  // 發送消息到服務器
  const sendMessage = () => {
    console.log(message);
    ws.send(message);
  };

  return (
    <div>
      <h1>WebSocket 測試</h1>
      <input
        type="text"
        value={message}
        onChange={(e) => setMessage(e.target.value)}></input>
      <button onClick={sendMessage}>發送消息</button>
      <p>伺服器返回的消息:{serverMessage}</p>
    </div>
  );
}

export default WebSocketComponent;

如果還有印象,可以發現ws的回傳透過React的useState直接渲染到前端頁面,比起用js+html還簡單非常多,且易懂

注意事項

const ws = new WebSocket('ws://localhost:8080');必須放在useEffect中,因為組件會不斷渲染且不會被算在卸載,會導致連接數量一直上升,可以試著移到外面觀察。

結論:

  • 使用 React 和 WebSocket 可以非常簡單地實現實時雙向通信。
  • WebSocket 的回傳消息通過 React 的 useState 直接渲染到頁面,讓應用的實時反應更加容易實現。
  • 相比傳統的 HTML 和 JavaScript,React 的組件化開發和狀態管理讓 WebSocket 集成變得更加簡潔和易懂。

更新10/5
這邊更新一下你在這邊用完之後可能會發現console那邊怎麼出現連接錯誤又成功呢?

那是因為 React 的 Strict Mode 導致的雙重渲染行為,導致useEffect照理來說的只會觸發一次但因為Strict Mode的關係二次觸發,導致連接兩次WebSocket也因此第一次被第二次打掉,就會報錯,但實質上是不影響的還是可以連接成功

如果把index.js下面改成

root.render(
    <App />
);

就能發現錯誤消失,也能透過useRef 來儲存 WebSocket 連接,就是這樣囉


上一篇
[day25]React Router 路由守衛與嵌套路由
下一篇
[day27]WebSocket 與 React 的狀態管理:實時更新數據(時鐘)
系列文
雙向奔赴的websocket與冰冷的react30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言